import { _decorator, Camera, CCFloat, Component, director, EventTouch, Node, v2, v3, Vec2, Vec3, view } from 'cc';
const { ccclass, property } = _decorator;

const weightVec = v2();
const dotDisplace = v2();
const curLocationPos = v3();
const startLocationPos = v2();
const v3_1 = v3();

@ccclass('PlayerControl')
export class PlayerControl extends Component {
    @property(Node)
    cameraNode!: Node;

    //控制节点
    @property(Node)
    controlNode!: Node;
    //控制节点
    @property(Node)
    dot!: Node;
    //玩家节点
    @property(Node)
    playerNode!: Node;
    @property(Node)
    headNode!: Node;
    //昵称
    @property(Node)
    nickname!: Node;

    @property({ type: CCFloat, tooltip: "触摸最大移动半径" })
    maxDistance: number = 80;

    /** 控制圆环 */
    private circleDot!: Node;

    protected onLoad(): void {
        this.circleDot = this.dot.parent!;
    }

    protected onEnable(): void {
        //触摸监听
        this.controlNode.on(Node.EventType.TOUCH_START, this._onTouchStart, this);
        this.controlNode.on(Node.EventType.TOUCH_MOVE, this._onTouchMove, this);
        this.controlNode.on(Node.EventType.TOUCH_END, this._onTouchEnd, this);
        this.controlNode.on(Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
    }

    protected onDisable(): void {
        this.controlNode.targetOff(this);
    }

    private _onTouchStart(e: EventTouch) {
        this.dot.position = v3(0, 0)
        this._onMoveStart(e);
    }

    private _onTouchMove(e: EventTouch) {
        this._onMoving(e);
    }
    private _onTouchEnd(e: EventTouch) {
        this._onMoveEnd(e);
    }
    private _onTouchCancel(e: EventTouch) {
        this._onMoveCancel(e);
    }

    private _onMoveStart(e: EventTouch) {
        this.circleDot.active = true;
        let Ipos = e.getUILocation(startLocationPos);
        this.circleDot.position = curLocationPos.set(Ipos.x, Ipos.y);

    }
    private _onMoving(e: EventTouch) {
        e.getStartLocation(startLocationPos);
        e.getLocation(dotDisplace);
        dotDisplace.subtract(startLocationPos);
        if (dotDisplace.length() == 0) {
            return;
        }

        this.circleDot.active = true;
        if (dotDisplace.length() > this.maxDistance) { dotDisplace.normalize().multiplyScalar(this.maxDistance); }
        this.dot.position = curLocationPos.set(dotDisplace.x, dotDisplace.y);
        dotDisplace.y = -dotDisplace.y;
    }
    private _onMoveEnd(e: EventTouch) {
        dotDisplace.set(Vec2.ZERO);
        startLocationPos.set(Vec2.ZERO);
        this.circleDot.active = false;
    }
    private _onMoveCancel(e: EventTouch) {
        dotDisplace.set(Vec2.ZERO);
        startLocationPos.set(Vec2.ZERO);
        this.circleDot.active = false;
    }

    protected update(dt: number): void {
        this._updateNickname();
        if (!dotDisplace.equals(startLocationPos)) {
            weightVec.set(dotDisplace).multiplyScalar(1 / 800)
            let v3_2 = this.playerNode.getPosition().add(new Vec3(weightVec.x, 0, weightVec.y));
            // 设置玩家位置，与摄像机Z轴最近距离
            if (v3_2.z < 13) {
                this.playerNode.setPosition(v3_2);
            }
        }
    }

    private _updateNickname() {
        let camera = this.cameraNode.getComponent(Camera);
        let isView = this.pointInViewport(this.headNode.worldPosition, camera);
        // 改变ui的显示状态
        this.nickname.active = isView;
        // 物体不在摄像机范围内隐藏
        if (!isView) {
            return;
        }

        const wpos = this.headNode.worldPosition;
        // 把3D空间世界坐标转本地节点坐标
        camera.convertToUINode(wpos, this.nickname.parent, v3_1);
        this.nickname!.setPosition(v3(v3_1.x, v3_1.y + 50, v3_1.z));

        // 节点的世界坐标转到摄像机下的坐标
        Vec3.transformMat4(v3_1, this.headNode.worldPosition, camera['_camera']!.matView);
    }

    /**
     * 检测世界点是否在屏幕内
     * @param worldPoint 世界点
     * @param camera3d 
     */
    public pointInViewport(worldPoint: Vec3, camera3d: Camera): boolean {
        var { x, y } = camera3d.worldToScreen(worldPoint, v3(0)), rect = view.getViewportRect(), sub = 20;
        return x > -sub && x < rect.width + sub && y > -sub && y < rect.height + sub;
    }
}


